#include <cjson/cJSON.h> //cjson
#include <curl/curl.h>   //libcurl
#include <curl/easy.h>
#include <stdio.h>
#include <stdlib.h> //free
#include <string.h> //strlen
#include "mqtt.h"

//删除字符串结尾换行
void trim(char *s)
{
    s[strcspn(s, "\r\n")] = 0;
}

//发送HTTP请求，并接收响应消息
char *send_request(char *question)
{
    //创建内存流
    //参数1：指向内存流中内容的指针
    //参数2：内存流中内容的大小
    char *response = NULL;
    size_t resplen = 0;
    FILE *fp = open_memstream(&response, &resplen);
    if (!fp)
    {
        perror("open_memstream");
        return NULL;
    }

    trim(question);

    //初始化HTTP客户端
    //成功返回客户端句柄，失败返回NULL
    CURL *client = curl_easy_init();
    if (!client)
    {
        perror("curl_easy_init");
        fclose(fp);
        return NULL;
    }

    //将输入的字符进行URL编码（将中文和保留字符编码成百分号编码）
    char *encoded_question = curl_easy_escape(client, question, strlen(question));
    // printf("%s\n", encoded_question);

    //自动分配缓冲区，将参数2中的内容写入缓冲区
    char *url = NULL;
    asprintf(&url, "http://api.qingyunke.com/api.php?key=free&appid=0&msg=%s", encoded_question);

    //释放curl_easy_escape分配的内存
    curl_free(encoded_question);

    //设置HTTP请求地址
    curl_easy_setopt(client, CURLOPT_URL, url);

    //设置响应消息正文写入内存流中
    curl_easy_setopt(client, CURLOPT_WRITEDATA, fp);

    //发送HTTP请求
    CURLcode error = curl_easy_perform(client);
    if (error != CURLE_OK)
    {
        printf("send request error: %s\n", curl_easy_strerror(error));
        free(url);
        fclose(fp);
        free(response);
        curl_easy_cleanup(client);
        return NULL;
    }

    free(url);
    //关闭内存流，然后才能访问内存流中的内容
    fclose(fp);

    // printf("%s\n", response);

    //释放客户端占用内存
    curl_easy_cleanup(client);

    return response;
}

//解析响应报文
void handle_response(char *response)
{
    cJSON *obj = cJSON_Parse(response);
    if (obj)
    {
        cJSON *content = cJSON_GetObjectItem(obj, "content");
        if (content)
        {
            puts(content->valuestring);
        }
        cJSON_Delete(obj);
    }
}

char line[BUFSIZ];

int main()
{
    //将标准输出设置为行缓冲（默认全缓冲）
    setlinebuf(stdout);

    mqtt_init();

    //从标准输入读取一行字符
    //参数1：保存输入内容的缓冲区
    //参数2：缓冲区大小
    //参数3：标准输入的文件流指针
    //返回值：成功返回缓冲区指针，失败或读到文件结束返回NULL
    //输入ctrl+d退出循环
    while (fgets(line, sizeof(line), stdin))
    {
        if (strstr(line, "开灯"))
        {
            //发送开灯命令
            set_status("lamp", 0, 1);
            puts("灯已打开");
            continue;
        }

        if (strstr(line, "关灯"))
        {
            //发送关灯命令
            set_status("lamp", 0, 0);
            puts("灯已关闭");
            continue;
        }

        if (strstr(line, "打开报警器"))
        {
            set_status("alarm", 0, 1);
            puts("报警器已打开");
            continue;
        }

        if (strstr(line, "关闭报警器"))
        {
            set_status("alarm", 0, 0);
            puts("报警器已关闭");
            continue;
        }

        char *response = send_request(line);
        if (response)
        {
            handle_response(response);
            //释放内存
            free(response);
        }
    }

    mqtt_cleanup();

    return 0;
}
